package com.wangl.spring.service.chain;

import com.intellij.psi.*;
import com.intellij.psi.impl.compiled.ClsArrayInitializerMemberValueImpl;
import com.wangl.spring.suggestion.SuggestionNodeTree;
import com.wangl.spring.suggestion.SuggestionNodeType;
import com.wangl.spring.utils.Annotations;
import com.wangl.spring.utils.SpringBootPropertiesResolver;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang3.StringUtils;

import java.util.ArrayList;
import java.util.List;
import java.util.Objects;

/**
 * @ClassName ConditionOnPropertiesSuggestionTreeBuilder
 * @Description TODO
 * @Author wangl
 * @Date 2023/4/27 13:15
 */
public class ConditionOnPropertiesSuggestionTreeBuilder implements SuggestionTreeBuilder{
    @Override
    public void build(SuggestionNodeTree suggestionNodeTree, PsiClass psiClass) {
        if (SpringBootPropertiesResolver.isAnnotationConditionalOnProperty(psiClass)){
            PsiAnnotation annotation = psiClass.getAnnotation(Annotations.CONDITIONAL_ON_PROPERTY);
            List<String> suggestions = getSuggestions(annotation);
            if (CollectionUtils.isNotEmpty(suggestions)){
                for (String suggestion : suggestions) {
                    suggestionNodeTree.insertNode(suggestion, psiClass, SuggestionNodeType.ANNOTATION_CONDITIONAL_ON_PROPERTY);
                }
            }
        }
        PsiMethod[] allMethods = psiClass.getAllMethods();
        for (PsiMethod method : allMethods) {
            build(suggestionNodeTree, method);
        }
    }

    @Override
    public void build(SuggestionNodeTree suggestionNodeTree, PsiMethod psiMethod) {
        PsiAnnotation annotation = psiMethod.getAnnotation(Annotations.CONDITIONAL_ON_PROPERTY);
        if (annotation != null){
            List<String> suggestions = getSuggestions(annotation);
            if (CollectionUtils.isNotEmpty(suggestions)){
                for (String suggestion : suggestions) {
                    suggestionNodeTree.insertNode(suggestion, psiMethod, SuggestionNodeType.ANNOTATION_CONDITIONAL_ON_PROPERTY);
                }
            }
        }
    }

    @Override
    public void build(SuggestionNodeTree suggestionNodeTree, PsiField psiField) {

    }

    private List<String> getSuggestions(PsiAnnotation annotation){
        List<String> suggestions = new ArrayList<>();
        String prefixStr = "";
        PsiAnnotationMemberValue prefix = annotation.findAttributeValue("prefix");
        if (prefix instanceof PsiLiteralExpression){
            prefixStr += Objects.requireNonNull(((PsiLiteralExpression) prefix).getValue());
            if (prefixStr.length() > 0){
                prefixStr += ".";
            }
        }
        PsiAnnotationMemberValue name = annotation.findAttributeValue("name");
        if (name instanceof ClsArrayInitializerMemberValueImpl){
            PsiAnnotationMemberValue[] names = ((ClsArrayInitializerMemberValueImpl) name).getInitializers();
            for (PsiAnnotationMemberValue nameExp : names) {
                if (nameExp instanceof PsiLiteralExpression){
                    suggestions.add(prefixStr + Objects.requireNonNull(((PsiLiteralExpression) nameExp).getValue()));
                }
            }
            if (CollectionUtils.isNotEmpty(suggestions)){
                return suggestions;
            }
        }
        PsiAnnotationMemberValue value = annotation.findAttributeValue("value");
        if (value instanceof ClsArrayInitializerMemberValueImpl){
            PsiAnnotationMemberValue[] values = ((ClsArrayInitializerMemberValueImpl) value).getInitializers();
            for (PsiAnnotationMemberValue valueExp : values) {
                if (valueExp instanceof PsiLiteralExpression){
                    suggestions.add(prefixStr + Objects.requireNonNull(((PsiLiteralExpression) valueExp).getValue()));
                }
            }
            return suggestions;
        }
        return suggestions;
    }
}
